#include "snake.h"
#include "ui_snake.h"

snake::snake(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::snake)
{
        ui->setupUi(this);
        this->setFocusPolicy(Qt::StrongFocus);
        this->setFocus();
        grade = 0;
        life = 100;
        QRandomGenerator generator;
        // 使用当前时间戳来设置种子，确保每次运行时生成不同的随机数
        generator.seed(QDateTime::currentMSecsSinceEpoch());
         QSet<QPoint> uniquePoints;  // 使用 QSet 来确保唯一性
        // 生成蛇头出生点随机数
        snakerow = generator.bounded(28);//列
        snakeclo = generator.bounded(40);//行
        //QPoint point(snakerow,snakeclo);

        snakelist.append(QPoint(snakerow,snakeclo));
        snakelist.append(QPoint(snakerow,snakeclo+1));
        snakelist.append(QPoint(snakerow,snakeclo+2));
        int sx =  snakerow;
        int sy = snakeclo;
        uniquePoints.insert(QPoint(sx, sy));  // 将坐标插入 QSet，自动去重
        uniquePoints.insert(QPoint(sx, sy+1));
        uniquePoints.insert(QPoint(sx, sy+2));

        while(uniquePoints.size() <= 28)
        {
            //生成1个食物坐标
            int foodrow = generator.bounded(28);//列
            int foodclo = generator.bounded(40);//行
            uniquePoints.insert(QPoint(foodrow,foodclo));
        }
        uniquePoints.remove(QPoint(sx, sy));
        uniquePoints.remove(QPoint(sx, sy+1));
        uniquePoints.remove(QPoint(sx, sy+2));
        // 使用迭代器将 QSet 中的所有元素添加到 QList 中
        for (const QPoint& point : uniquePoints) {
            food.append(point);
        }



        uniquePoints.insert(QPoint(sx, sy));  // 将坐标插入 QSet，自动去重
        uniquePoints.insert(QPoint(sx, sy+1));
        uniquePoints.insert(QPoint(sx, sy+2));
        while(uniquePoints.size() <= 53)
        {
            //生成1个障碍物坐标
            int fencerow = generator.bounded(28);//列
            int fenceclo = generator.bounded(40);//行
            uniquePoints.insert(QPoint(fencerow,fenceclo));
        }
        uniquePoints.remove(QPoint(sx, sy));
        uniquePoints.remove(QPoint(sx, sy+1));
        uniquePoints.remove(QPoint(sx, sy+2));
        // QList<QPoint> list;
        // 遍历 food 中的每个点并删除在 list 中相同的点
        for (const QPoint &point : food) {
            uniquePoints.remove(point);  // 删除所有与 point 相同的坐标
        }
        // 使用迭代器将 QSet 中的所有元素添加到 QList 中
        for (const QPoint& point : uniquePoints) {
            fence.append(point);
        }
        cellsize = 20;
        snakedir = Left;
        id = startTimer(500);
}

void snake::paintEvent(QPaintEvent *event)
{
    this->setFocusPolicy(Qt::StrongFocus);

    QPainter  Painter(this);
    Painter.drawRect(QRect(0,0,ui->widget->width(),ui->widget->height()));

    //画格子
    for(int i=1;i <= ui->widget->height()/cellsize;i++)
    {
        Painter.drawLine(0,i*cellsize,this->width(),i*cellsize);
    }
    for(int i=1;i <= ui->widget->width()/cellsize;i++)
    {
        Painter.drawLine(i*cellsize,0,i*cellsize,ui->widget->height());
    }
            //如果碰到边界直接弹窗
            if(snakerow == -1 || snakeclo == -1 || snakerow == 28 || snakeclo == 40)
            {
                QMessageBox msgBox;
                msgBox.setIcon(QMessageBox::Information);  // 设置图标为信息图标
                msgBox.setWindowTitle("Information");      // 设置窗口标题
                msgBox.setText("你已死亡！");  // 设置消息框的文本
                msgBox.setInformativeText(QString("你已死亡,你获得的最终分数为：%1").arg(grade));  // 设置详细信息（可选）
                msgBox.setStandardButtons(QMessageBox::Ok);  // 只添加一个“OK”按钮
                msgBox.setDefaultButton(QMessageBox::Ok);    // 设置默认按钮为“OK“
                // 显示消息框并等待用户点击按钮
                msgBox.exec();
                this->close();
            }
            //如果生命归0也弹窗
            if(life == 0)
            {
                QMessageBox msgBox;
                msgBox.setIcon(QMessageBox::Information);  // 设置图标为信息图标
                msgBox.setWindowTitle("Information");      // 设置窗口标题
                msgBox.setText("你已死亡！");  // 设置消息框的文本
                msgBox.setInformativeText(QString("你获得的最终分数为：%1").arg(grade));  // 设置详细信息（可选）
                msgBox.setStandardButtons(QMessageBox::Ok);  // 只添加一个“OK”按钮
                msgBox.setDefaultButton(QMessageBox::Ok);    // 设置默认按钮为“OK“
                // 显示消息框并等待用户点击按钮
                msgBox.exec();
                this->close();
            }
            //如果食物全部吃完也弹窗
            if(food.size() == 0)
            {
                QMessageBox msgBox;
                msgBox.setIcon(QMessageBox::Information);  // 设置图标为信息图标
                msgBox.setWindowTitle("information");      // 设置窗口标题
                msgBox.setText("你已吃掉全部食物!");  // 设置消息框的文本
                msgBox.setInformativeText(QString("你获得的最终分数为：%1").arg(grade));  // 设置详细信息（可选）
                msgBox.setStandardButtons(QMessageBox::Ok);  // 只添加一个“OK”按钮
                msgBox.setDefaultButton(QMessageBox::Ok);    // 设置默认按钮为“OK“
                // 显示消息框并等待用户点击按钮
                msgBox.exec();
                this->close();
            }


    Painter.setBrush(Qt::red);//设置画图形填充色为红色
    //画食物
    for (int j = 0;j<food.size();j++) {
        Painter.drawEllipse(QRect(food[j].y()*cellsize,food[j].x()*cellsize,cellsize,cellsize));
    }
    Painter.setBrush(Qt::black);//设置画图形填充色为黑色
    //画障碍物
    for (int j = 0;j<fence.size();j++) {
        Painter.drawEllipse(QRect(fence[j].y()*cellsize,fence[j].x()*cellsize,cellsize,cellsize));
    }
    Painter.setBrush(Qt::blue);//设置画图形填充色为蓝色
    //画蛇
    for (int k = 0;k<snakelist.size();k++) {
        Painter.drawEllipse(QRect(snakelist[k].y()*cellsize,snakelist[k].x()*cellsize,cellsize,cellsize));
    }
}

//蛇头根据按键移动
void snake::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_W && snakedir != Down)
    {
        snakedir = Up;
    }
    else if(event->key() == Qt::Key_S && snakedir != Up)
    {
        snakedir = Down;
    }
    else if(event->key() == Qt::Key_A && snakedir != Right)
    {
        snakedir = Left;
    }
    else if(event->key() == Qt::Key_D && snakedir != Left)
    {
        snakedir = Right;
    }
}

//
void snake::timerEvent(QTimerEvent *e)
{
    // 保存蛇头当前的位置
    QPoint head = snakelist.first();
    switch(snakedir)
    {
    case Up:
        snakerow--;
        head.setX(head.x() - 1);
        break;
    case Down:
        snakerow++;
        head.setX(head.x() + 1);
        break;
    case Left:
        snakeclo--;
        head.setY(head.y() - 1);
        break;
    case Right:
        snakeclo++;
        head.setY(head.y() + 1);
        break;
    }
    // 在蛇头前插入新坐标
    snakelist.prepend(head);
    // 移除蛇尾
    snakelist.removeLast();
    eat_food();
    eat_fence();

    repaint();
}

//吃豆子
void snake::eat_food()
{
    // 保存蛇头当前的位置
    QPoint head = snakelist.first();
    for(auto it = food.begin();it != food.end();)
    {
        if(head == *it)
        {
            snakelist.prepend(*it);
            it = food.erase(it);
            grade+=10;
            ui->lcdNumber->display(grade);
        }
        else
        {
            ++it;
        }
    }
}

void snake::eat_fence()
{
    //保存当前位置
    QPoint head = snakelist.first();
    for(auto it = fence.begin();it != fence.end();)
    {
        if(head == *it)
        {
            it = fence.erase(it);
            grade-=10;
            life-=10;
            ui->lcdNumber->display(grade);
            ui->progressBar->setValue(life);
        }
        else
        {
            ++it;
        }
    }
}


void snake::keyReleaseEvent(QKeyEvent *event)
{

}

void snake::resetTimer(int mill)
{
    // 停止定时器
    killTimer(id);
    id = startTimer(mill);  // 重置定时器ID
}

snake::~snake()
{
    delete ui;
}

void snake::on_comboBox_currentTextChanged(const QString &arg1)
{
    if(arg1 == "简单")
    {
        resetTimer(500);
    }
    else if(arg1 == "中等")
    {
        resetTimer(250);
    }
    else if(arg1 == "困难")
    {
        resetTimer(80);
    }
}

